package com.family.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.family.model.system.SysMenu;
import com.family.model.system.SysRoleMenu;
import com.family.model.vo.AssignMenuVo;
import com.family.system.mapper.SysMenuMapper;
import com.family.system.mapper.SysRoleMenuMapper;
import com.family.system.service.SysMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName SysMenuServiceImpl
 * @Date 2023-05-09 10:22
 * @AUTHOR family
 **/
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private SysMenuMapper sysMenuMapper;
    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;

    @Override
    public List<SysMenu> findSysMenuByRoleId(Long roleId) {
        //获取所有status为1的权限列表
        LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysMenu::getStatus, "1");
        List<SysMenu> menuList = sysMenuMapper.selectList(queryWrapper);
        //根据角色id获取角色权限
        List<SysRoleMenu> roleMenuList = sysRoleMenuMapper.selectList(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, roleId));
        //获取该角色已分配的所有权限id
        List<Long> roleMenus = new ArrayList<>();
        for (SysRoleMenu roleMenu : roleMenuList) {
            roleMenus.add(roleMenu.getMenuId());
        }
        //遍历所有权限列表将已分配的属性 seletc 设置默认值
        for (SysMenu sysMenu : menuList) {
            //设置权限分配状态
            sysMenu.setSelect(roleMenus.contains(sysMenu.getId()));
        }
        //将权限列表转换成权限树
        menuList = buildTree(menuList);
        return menuList;
    }

    @Transactional
    @Override
    public void doAssign(AssignMenuVo assignMenuVo) {
        //删除已分配的权限
        sysRoleMenuMapper.delete(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, assignMenuVo.getRoleId()));
        //遍历所有已选择的权限id
        List<Long> menuIdList = assignMenuVo.getMenuIdList();
        for (Long menuId : menuIdList) {
            if (menuId != null) {
                SysRoleMenu roleMenu = new SysRoleMenu();
                roleMenu.setMenuId(menuId);
                roleMenu.setRoleId(assignMenuVo.getRoleId());
                sysRoleMenuMapper.insert(roleMenu);
            }
        }
    }

    @Override
    public List<String> findUserPermsList(Long userId) {
        List<SysMenu> sysMenuList = null;
        if (userId.longValue() == 1) {
            sysMenuList = list(new LambdaQueryWrapper<SysMenu>().eq(SysMenu::getStatus, 1));
        } else {
            sysMenuList = baseMapper.selectMenuListByUserId(userId);
        }
        return sysMenuList.stream()
                .filter(item -> item.getType() == 2)
                .map(SysMenu::getPerms)
                .collect(Collectors.toList());
    }

    @Override
    public List<SysMenu> findNodes() {
        //查询所有的菜单
        List<SysMenu> menuList = list();
        if (CollectionUtils.isEmpty(menuList))
            return null;
        //构建树形数据
        menuList = buildTree(menuList);
        //存入缓存中
        redisTemplate.opsForValue().set("menuList", menuList);
        return menuList;
    }


    /**
     * 构建菜单树
     *
     * @param menuList
     * @return
     */
    public static List<SysMenu> buildTree(List<SysMenu> menuList) {
        List<SysMenu> trees = new ArrayList<>();
        for (SysMenu sysMenu : menuList) {
            if (0 == sysMenu.getParentId().longValue()) {
                trees.add(findChildren(sysMenu, menuList));
            }
        }

        return trees;
    }

    /**
     * 递归调用子菜单
     *
     * @param sysMenu
     * @param treeNodes
     * @return
     */
    public static SysMenu findChildren(SysMenu sysMenu, List<SysMenu> treeNodes) {
        sysMenu.setChildren(new ArrayList<SysMenu>());
        for (SysMenu treeNode : treeNodes) {
            if (sysMenu.getId().longValue() == treeNode.getParentId().longValue()) {
                sysMenu.getChildren().add(findChildren(treeNode, treeNodes));
            }
        }
        return sysMenu;
    }
}
